﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading;

using RaisingStudio.SmallProgram.Library.Internal;

namespace RaisingStudio.SmallProgram.Library
{
    [SmallProgramType]
    public static class Sound
    {
        private static int _defaultLength = 4;
        private static int _octave = 4;
        private static Dictionary<string, int> _notes = new Dictionary<string, int>();

        static Sound()
        {
            _notes.Add("C", 0);
            _notes.Add("C+", 1);
            _notes.Add("C#", 1);
            _notes.Add("D-", 1);
            _notes.Add("D", 2);
            _notes.Add("D+", 3);
            _notes.Add("D#", 3);
            _notes.Add("E-", 3);
            _notes.Add("E", 4);
            _notes.Add("F", 5);
            _notes.Add("F+", 6);
            _notes.Add("F#", 6);
            _notes.Add("G-", 6);
            _notes.Add("G", 7);
            _notes.Add("G+", 8);
            _notes.Add("G#", 8);
            _notes.Add("A-", 8);
            _notes.Add("A", 9);
            _notes.Add("A+", 10);
            _notes.Add("A#", 10);
            _notes.Add("B-", 10);
            _notes.Add("B", 11);
        }


        private static Stream GetSoundStream(string fileName)
        {
            Assembly executingAssembly = Assembly.GetExecutingAssembly();
            string name = string.Format("Sounds.{0}", fileName);
            return executingAssembly.GetManifestResourceStream(typeof(Sound), name);
        }

        public static void Pause(Primitive filePath)
        {
            // TODO:
        }

        public static void Play(Primitive filePath)
        {
            // TODO:
        }

        public static void PlayAndWait(Primitive filePath)
        {
            // TODO:
        }

        public static void PlayBellRing()
        {
            PlayStockSound("BellRing.wav", false);
        }

        public static void PlayBellRingAndWait()
        {
            PlayStockSound("BellRing.wav", true);
        }

        public static void PlayChime()
        {
            PlayStockSound("Chime.wav", false);
        }

        public static void PlayChimeAndWait()
        {
            PlayStockSound("Chime.wav", true);
        }

        public static void PlayChimes()
        {
            PlayStockSound("Pause.wav", false);
        }

        public static void PlayChimesAndWait()
        {
            PlayStockSound("Pause.wav", true);
        }

        public static void PlayClick()
        {
            PlayStockSound("Click.wav", false);
        }

        public static void PlayClickAndWait()
        {
            PlayStockSound("Click.wav", true);
        }

        public static void PlayMusic(Primitive notes)
        {
            Midi.EnsureDeviceInit();
            PlayNotes((string)notes);
        }

        private static void PlayNote(int number)
        {
            Midi.PlayNote(number);
        }

        private static void PlayNote(int octave, string note, int length)
        {
            double num = 1600.0 / ((double)length);
            if ((note == "P") || (note == "R"))
            {
                Thread.Sleep((int)num);
            }
            else if (note == "L")
            {
                _defaultLength = length;
            }
            else
            {
                int num2;
                if (!_notes.TryGetValue(note, out num2))
                {
                    num2 = 0;
                }
                octave = (int)Math.Min(Math.Max(0, octave), 8);
                int number = (octave * 12) + num2;
                PlayNote(number);
                Thread.Sleep((int)num);
            }
        }

        private static void PlayNotes(string song)
        {
            int i = 0;
            song = song.ToUpperInvariant();
            int length = song.Length;
            while (i < song.Length)
            {
                string node;
                int num = _defaultLength;
                char c = song[i++];
                if (char.IsLetter(c))
                {
                    node = new string(c, 1);
                }
                else
                {
                    if (c == '>')
                    {
                        _octave = (int)Math.Min(8, _octave + 1);
                    }
                    else if (c == '<')
                    {
                        _octave = (int)Math.Max(0, _octave - 1);
                    }
                    continue;
                }
                if (i < length)
                {
                    c = song[i];
                    if (c == '#' || c == '+' || c == '-')
                    {

                        node += new string(c, 1);
                        i++;
                    }
                    if (i < length)
                    {
                        c = song[i];
                        if (char.IsDigit(c))
                        {
                            num = c - '0';
                            i++;
                        }
                        if (i < length)
                        {
                            c = song[i];
                            if (char.IsDigit(c))
                            {
                                num = (num * 10) + (c - '0');
                                i++;
                            }
                        }
                    }
                }
                if (node[0] == 'O')
                {
                    _octave = num;
                }
                else
                {
                    PlayNote(_octave, node, num);
                }
            }
        }

        private static void PlayStockSound(string name, bool sync)
        {
            // TODO:
        }

        public static void Stop(Primitive filePath)
        {
            // TODO:
        }
    }
}

